package it.leehook.mp3.utils;

import it.leehook.mp3.activities.MainActivity;

import java.io.File;
import java.io.RandomAccessFile;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.jaudiotagger.audio.AudioFile;
import org.jaudiotagger.audio.mp3.MP3FileReader;
import org.jaudiotagger.audio.mp4.Mp4TagReader;
import org.jaudiotagger.audio.ogg.OggFileReader;
import org.jaudiotagger.tag.FieldKey;
import org.jaudiotagger.tag.Tag;
import org.jaudiotagger.tag.TagOptionSingleton;
import org.jaudiotagger.tag.mp4.Mp4Tag;

import android.app.Activity;

/**
 * Classe di utility per la gestione dei file musicali
 * 
 * @author leehook
 * 
 */
public class SongUtils extends Activity {

	/**
	 * Verifica l'album appena recuperato dal file musicale. Se questo e' vuoto,
	 * null, sconosciuto o unknkown, lo valorizza col titolo della canzone
	 * 
	 * @param album
	 * @return
	 * @throws Exception
	 */
	private String checkAlbum(String album, String titolo) throws Exception {
		if (StringUtils.isBlank(album)
				|| StringUtils.equalsIgnoreCase(album, "unknown")
				|| StringUtils.equalsIgnoreCase(album, "sconosciuto")) {
			return titolo;
		} else {
			return album;
		}
	}

	/**
	 * Legge i tag ID3 del file M4A
	 * 
	 * @throws Exception
	 */
	public void checkM4ATags(File file) throws Exception {
		RandomAccessFile m4aFile = new RandomAccessFile(file, "rw");
		Mp4Tag m4aTags = new Mp4TagReader().read(m4aFile);
		updateTags(m4aTags, file, null);
	}

	/**
	 * Legge i tag ID3 del file MP3
	 * 
	 * @throws Exception
	 */
	public void checkMP3Tags(File file) throws Exception {
		AudioFile audio = new MP3FileReader().read(file);
		Tag tag = audio.getTag();
		updateTags(tag, file, audio);
	}

	/**
	 * Legge i tag ID3 del file OGG
	 * 
	 * @throws Exception
	 */
	public void checkOGGTags(File file) throws Exception {
		AudioFile audioFile = new OggFileReader().read(file);
		Tag oggTags = audioFile.getTag();
		updateTags(oggTags, file, null);
	}

	/**
	 * Legge i tag ID3 del file WAV/WMA
	 * 
	 * @throws Exception
	 */
	public void checkWAVTags(File file) throws Exception {
		AudioFile audioFile = new AudioFile();
		audioFile.setFile(file);
		Tag audioTags = audioFile.getTag();
		updateTags(audioTags, file, audioFile);
	}

	/**
	 * Elimina le cartelle rimaste vuote dopo lo spostamento dei file
	 * 
	 * @param path
	 * @throws Exception
	 */
	public static void cleanEmptyDirs(File path) {
		File[] list = path.listFiles();
		for (File file : list) {
			if (file.isDirectory()) {
				File[] files = file.listFiles();
				if (files.length == 0) {
					file.delete();
				} else {
					cleanEmptyDirs(file.getAbsoluteFile());
				}
			}
		}
	}

	/**
	 * Pulisce i valori dei tag (artista, album, titolo) dai caratteri non
	 * consentiti
	 * 
	 * @param tagValue
	 * @return
	 * @throws Exception
	 */
	public String cleanTagName(String tagValue) throws Exception {
		String returnValue = tagValue;
		returnValue = tagValue.replaceAll("[\\\\?/]", "_");
		return returnValue;
	}

	/**
	 * Aggiorna i tag del file
	 * 
	 * @param tag
	 * @param file
	 * @throws Exception
	 */
	private void updateTags(Tag tag, File file, AudioFile audio)
			throws Exception {
		String artista = "";
		String album = "";
		String titolo = "";
		String numeroCanzone = "";
		if (tag != null) {
			artista = tag.getFirst(FieldKey.ARTIST);
			album = tag.getFirst(FieldKey.ALBUM);
			titolo = tag.getFirst(FieldKey.TITLE);
			numeroCanzone = tag.getFirst(FieldKey.TRACK);
		} else {
			// il file non contiene Tag. Lo creo e gli setto i valori splittando
			// il nome del file in base a '#' in quanto gTunes crea i file col
			// nome titolo#artista#album#.estensione
			tag = audio.createDefaultTag();
			String[] infoSong = StringUtils.split(file.getName(), "#");
			titolo = StringUtils.replace(infoSong[0], "_", " ");
			artista = StringUtils.replace(infoSong[1], "_", " ");
			album = StringUtils.replace(infoSong[2], "_", " ");
		}
		album = StringUtils.replace(album, "Iii", "III");
		album = StringUtils.replace(album, "Ii", "II");
		// Scrivo bene i tag. Prima cancello quelli esistenti e poi scrivo i
		// miei
		tag.deleteField(FieldKey.ARTIST);
		tag.deleteField(FieldKey.ALBUM_ARTIST);
		tag.deleteField(FieldKey.TITLE);
		tag.deleteField(FieldKey.ALBUM);
		tag.deleteField(FieldKey.COMMENT);

		tag.addField(FieldKey.ARTIST, WordUtils.capitalizeFully(artista));
		tag.addField(FieldKey.TITLE, WordUtils.capitalizeFully(titolo));
		tag.addField(FieldKey.GENRE, "Rock");
		tag.addField(FieldKey.ALBUM,
				WordUtils.capitalizeFully(checkAlbum(album, titolo)));
		TagOptionSingleton.getInstance().setAndroid(true);

		if (audio == null) {
			audio = new AudioFile();
			audio.setFile(file);
		}
		audio.setTag(tag);
		audio.commit();
		createSongTree(artista,
				WordUtils.capitalize(checkAlbum(album, titolo)), titolo,
				numeroCanzone, file);
	}

	/**
	 * Verifica l'alberatura della canzone e la sposta nella cartella
	 * "Artista"/"Album"
	 * 
	 * @param artista
	 * @param album
	 * @param titolo
	 * @param numeroCanzone
	 * @param originalFile
	 * @throws Exception
	 */
	private void createSongTree(String artista, String album, String titolo,
			String numeroCanzone, File originalFile) throws Exception {
		if (StringUtils.isBlank(artista) || StringUtils.isBlank(album)
				|| StringUtils.isBlank(titolo)) {
			throw new Exception("Tag non completi, verificarli");
		}
		String path = MainActivity.musicPath.getAbsolutePath() + File.separator
				+ WordUtils.capitalize(cleanTagName(artista)) + File.separator
				+ WordUtils.capitalize(cleanTagName(album));
		File pathFile = new File(path);
		String titoloSong = StringUtils.isBlank(numeroCanzone) ? WordUtils
				.capitalize(cleanTagName(titolo))
				+ "."
				+ StringUtils.lowerCase(originalFile.getName().substring(
						originalFile.getName().length() - 3)) : (numeroCanzone
				.length() > 1 ? numeroCanzone : "0" + numeroCanzone)
				+ " - "
				+ WordUtils.capitalize(cleanTagName(titolo))
				+ "."
				+ StringUtils.lowerCase(originalFile.getName().substring(
						originalFile.getName().length() - 3));
		if (!pathFile.exists()) {
			pathFile.mkdirs();
		}
		boolean successMove = originalFile.renameTo(new File(pathFile,
				titoloSong));
		if (!successMove) {
			System.err.println("Errore nello spostare la canzone " + titolo
					+ " da " + originalFile.getAbsolutePath() + " a "
					+ MainActivity.musicPath.getAbsolutePath());
			throw new Exception("Errore nello spostare la canzone " + titolo
					+ " da " + originalFile.getAbsolutePath() + " a "
					+ MainActivity.musicPath.getAbsolutePath());
		} else {
			System.out.println(titolo + " spostata correttamente in "
					+ pathFile.getAbsolutePath());
		}
	}
}
